#include "cw2015.h"
#include "driver/i2c.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

static const char *TAG = "cw2015";

static esp_err_t cw_write(uint8_t reg, const uint8_t *data, size_t len)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (CW2015_ADDR << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, reg, true);
    i2c_master_write(cmd, data, len, true);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_PORT, cmd, pdMS_TO_TICKS(I2C_TIMEOUT_MS));
    i2c_cmd_link_delete(cmd);
    return ret;
}

static esp_err_t cw_read(uint8_t reg, uint8_t *data, size_t len)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (CW2015_ADDR << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, reg, true);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (CW2015_ADDR << 1) | I2C_MASTER_READ, true);
    if (len > 1) i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
    i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_PORT, cmd, pdMS_TO_TICKS(I2C_TIMEOUT_MS));
    i2c_cmd_link_delete(cmd);
    return ret;
}

/*------------- 接口实现 -------------*/
esp_err_t cw2015_init(void)
{
    /* 等待芯片上电稳定 */
    vTaskDelay(pdMS_TO_TICKS(10));
    /* 检测版本寄存器 */
    uint8_t ver;
    esp_err_t ret = cw_read(0x00, &ver, 1);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "init failed");
        return ret;
    }
    ESP_LOGI(TAG, "chip version 0x%02X", ver);
    return ESP_OK;
}

esp_err_t cw2015_update_voltage(uint32_t* voltage)
{
    uint8_t buf[2];
    esp_err_t ret = cw_read(0x02, buf, 2);
    if (ret != ESP_OK) return ret;

    uint16_t raw = ((uint16_t)buf[0] << 8) | buf[1];        // 16-bit
    *voltage = raw * 305UL / 1000UL;                        // uV -> mV
    return ESP_OK;
}

esp_err_t cw2015_update_capacity(uint32_t* capacity)
{
    uint8_t buf[2];
    esp_err_t ret = cw_read(0x04, buf, 2);
    if (ret != ESP_OK) return ret;
    uint16_t soc = ((uint16_t)buf[0] << 8) | buf[1];
    *capacity = soc * 100 / 256;                           // 转成 0.01%
    return ESP_OK;
}

esp_err_t cw2015_release_alert_pin(uint8_t* alert_status)
{
    uint8_t rrt;
    esp_err_t ret = cw_read(0x06, &rrt, 1);
    if (ret != ESP_OK) return ret;
    *alert_status = (rrt >> 7) & 0x01; // bit7 是 ALRT 标志
    /* 读寄存器即清中断，无需额外操作 */
    return ESP_OK;
}

esp_err_t cw2015_set_alert_threshold(uint8_t threshold)
{
    if (threshold > 31) threshold = 31;
    uint8_t cfg;
    esp_err_t ret = cw_read(0x08, &cfg, 1);
    if (ret != ESP_OK) return ret;
    cfg = (cfg & 0xE0) | threshold;        // 低5位 = ATHD
    return cw_write(0x08, &cfg, 1);
}

esp_err_t cw2015_power_on_reset(void)
{
    uint8_t mode = 0x0C; // RESTART + QSTRT
    return cw_write(0x0A, &mode, 1);
}

esp_err_t cw2015_write_battery_profile(void)
{
    /* 1. 写 64-byte Profile */
    for (int i = 0; i < 64; i++) {
        uint8_t reg = 0x10 + i;
        uint8_t dat = cw_profile[i];
        esp_err_t ret = cw_write(reg, &dat, 1);
        if (ret != ESP_OK) {
            ESP_LOGE(TAG, "profile write fail @ %d", i);
            return ret;
        }
    }
    /* 2. 置 UPDATE_FLG */
    uint8_t cfg;
    cw_read(0x08, &cfg, 1);
    cfg |= 0x02;
    cw_write(0x08, &cfg, 1);
    /* 3. 重启算法 */
    cw2015_power_on_reset();
    ESP_LOGI(TAG, "battery profile written & activated");
    return ESP_OK;
}